
#include <string>
#include <cstdlib>
#include <sstream>
#include <iostream>

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


#include "game_errors.h"
#include "config.h"

using namespace std;

const string path_config("games.cfg");

void recreatePipe(const string& name_pipe){
	remove(name_pipe.c_str());
	string comand("mkfifo ");
	comand += name_pipe.c_str();
	comand += "\n";
	if (system(comand.c_str())){
		cerr << "Error in recreate pipe:" << name_pipe << endl;
		exit(1);
	}
};
void recreatePipes(Config& config){
	recreatePipe(config.getPathToPlayer1STDIN());
	recreatePipe(config.getPathToPlayer1STDOUT());
	recreatePipe(config.getPathToPlayer2STDIN());
	recreatePipe(config.getPathToPlayer2STDOUT());
};

void removePipes(Config& config){
	remove(config.getPathToPlayer1STDIN().c_str());
	remove(config.getPathToPlayer1STDOUT().c_str());
	remove(config.getPathToPlayer2STDIN().c_str());
	remove(config.getPathToPlayer2STDOUT().c_str());

}

int main(){
	Config config("games.cfg");
	recreatePipes(config);
	static pid_t player1, player2, checker;
	u_int game_result;
	if ((player1 = fork()) == -1){
		perror("create process of player1");
	};
	if (!player1){
		//player1
		string shell_p1("./");
		shell_p1 += config.getPathToPlayer1();
		shell_p1 += " 1 <";
		shell_p1 += config.getPathToPlayer1STDIN();
		shell_p1 += " >";
		shell_p1 += config.getPathToPlayer1STDOUT();
		//cerr << shell_p1;
		system(shell_p1.c_str());
	}else if ((player2 = fork()) == -1){
		perror("create process of player2");
	}else if (!player2){
		//player1
		string shell_p2("./");
		shell_p2 += config.getPathToPlayer2();
		shell_p2 += " 2 <";
		shell_p2 += config.getPathToPlayer2STDIN();
		shell_p2 += " >";
		shell_p2 += config.getPathToPlayer2STDOUT();
		//cerr << shell_p2;
		system(shell_p2.c_str());
	}else if ((checker = fork()) == -1){
		perror("create process of checker");
	}else if (!checker){
		//checker
		game_result = system(string("./" + config.getPathToChecker()).c_str());
		system(string("killall " + config.getPathToPlayer1() + " " + config.getPathToPlayer2()).c_str());		
		_exit(0);
	}else{
		//game_run
		waitpid(checker, NULL, 0);
		ifstream result("result.txt");
		result >> game_result;
		result.close();
		//выводим на экран информацию
		switch (getFlag(game_result))
		{
			case PIPE_NO_FOUND:
				cout << "pipes not found.";
				break;
			case FIRST_WINS:
				cout << "Player1 WIN.\nScore:" << getNumberScore(game_result) << endl;
				break;
			case SECOND_WINS:
				cout << "Player 2 WIN.\n Score:" << getNumberScore(game_result) << endl;
				break;
			case DRAW:
				cout << "Draw. \n Score:" << getNumberScore(game_result) << endl;
				break;
			case FORMAT_ERROR:
				cout << "Некорректные данные были выведены одним из ботов.\n";
				break;
			case TIME_LIMIT:
				cout << "Time limit for player " << getNumberScore(game_result);
				break;
			case MAP_FORMAT_ERROR:
				cout << "Error in format map file." << endl;
				break;
			case MAP_LOAD_SAVE_ERROR:
				cout << "Error in saving or loading map." << endl;
				break;
			default:;
				
		}
		removePipes(config);
		return 0;
	}
}
